package main

import (
  "fmt"
  "log"
  "os"
  "bytes"
  "encoding/json"
  "io/ioutil"
  "crypto/tls"
  "net/http"
  "strconv"
  "strings"
  "github.com/360EntSecGroup-Skylar/excelize/v2"
)

type Issue struct {  
	Id int
	Url string
  Number  string  
}

type Enterprise struct {
	Id int
	Type string
	Name string
	Path string
}

type Namespace struct {
	Id int
	Type string
	Name string
	Path string
	Parent Enterprise
}

type Project struct {  
	Id int
	FullName string
  Namespace Namespace 
}


func main() {
	if len(os.Args) != 4 { 
	  fmt.Println("参数个数有误，请根据 README 正确传参")
	  return
	}

  accessToken := os.Args[1]
  enterprisePath := os.Args[2]
  filePath := os.Args[3]
  namespaces := ""

  fmt.Println("导入开始...")

  f, err := excelize.OpenFile(filePath)

  if err != nil {
    log.Fatal(err)
  }

	for _, sheet := range f.GetSheetList() {
		if f.GetSheetVisible(sheet) {
	    rows, err := f.GetRows(sheet)
	    if err != nil {
        fmt.Println(err)
        return
	    }
	    for rowIndex, row := range rows {
	    	fmt.Println("正在导入第", strconv.Itoa(rowIndex + 1), "行。。。")
    		if len(row) == 0 {
    			continue
    		}
    		if rowIndex < 2 {
    			continue
    		}
    		if len(row[3]) == 0 {
				  fmt.Println("第", strconv.Itoa(rowIndex + 1), "行参数有误，「编码、标题、描述、代码仓地址」必填")
    			return
    		}
    		if len(row) > 4 && len(row[4]) > 0 {
    			continue
    		}

        title := row[0] + ":" + row[1]
        body := row[2]
        projectPath := row[3]

        projectUrl := strings.Split(projectPath, "/")
			  ownerPath := projectUrl[3]
			  repoPath := projectUrl[4]

			  repoValidate, newGroup := Validate(ownerPath, repoPath, enterprisePath, accessToken, namespaces)
			  if !repoValidate {
			  	return
			  }
			  if newGroup {
					namespaces = namespaces + "," + ownerPath
			  }
        number := Post(title, body, ownerPath, repoPath, accessToken)
			  fmt.Println(sheet, "E" + strconv.Itoa(rowIndex + 1), number)

			  f.SetCellValue(sheet, "E" + strconv.Itoa(rowIndex + 1), number)
			  if err = f.Save(); err != nil {
		      fmt.Println(err)
			  }
	    }
		}
	}
  fmt.Println("导入完成...")
}

func Validate(ownerPath, repoPath, enterprisePath, accessToken, namespaces string) (bool, bool) {
	if ownerPath == enterprisePath {
		return true, false
	}
	if strings.Contains(namespaces, ownerPath) {
		return true, false
	}
  url := fmt.Sprintf("https://gitee.com/api/v5/repos/%s/%s?access_token=%s", ownerPath, repoPath, accessToken)
  tr := &http.Transport{
  	TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  }
  client := &http.Client{Transport: tr}
  resp, err := client.Get(url)
  if err != nil {
    fmt.Println(err)
    os.Exit(1)
  }
  defer resp.Body.Close()
  respBytes, _ := ioutil.ReadAll(resp.Body)
	project := Project{}
	jsonErr := json.Unmarshal(respBytes, &project)
	if jsonErr != nil {
		log.Fatal(jsonErr)
	}
	if (project.Namespace.Parent.Type == "enterprise" && project.Namespace.Parent.Path == enterprisePath) {
		return true, true
	}
  fmt.Println(ownerPath, "/", repoPath, " 仓库不属于 ", enterprisePath, " 企业，请查证后重试")
	return false, false
}

func Post(title, description, ownerPath, repoPath, accessToken string) string {
  data := make(map[string]interface{})
  data["title"] = title
  data["body"] = description
  data["repo"] = repoPath
  url := fmt.Sprintf("https://gitee.com/api/v5/repos/%s/issues?access_token=%s", ownerPath, accessToken)

  bytesData, _ := json.Marshal(data)
  reader := bytes.NewReader(bytesData)
  request, err := http.NewRequest("POST", url, reader)
  if err != nil {
  	panic(err)
  }
  request.Header.Set("Content-Type", "application/json;charset=UTF-8")
  tr := &http.Transport{
  	TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  }
  client := &http.Client{Transport: tr}
  resp, err := client.Do(request)
  if err != nil {
  	panic(err)
  }
  respBytes, _ := ioutil.ReadAll(resp.Body)

	issue := Issue{}
	jsonErr := json.Unmarshal(respBytes, &issue)
	if jsonErr != nil {
		log.Fatal(jsonErr)
	}
  return string(issue.Number)
}

